package se.perp.c4.control;

import java.awt.Container;
import java.util.List;
import java.util.logging.Logger;
import se.perp.c4.control.iface.IGameController;
import se.perp.c4.control.iface.IMessenger;
import se.perp.c4.control.iface.ITerritorySelectionListener;
import se.perp.c4.model.Actor;
import se.perp.c4.model.Move;
import se.perp.c4.model.Territory;
import se.perp.c4.model.Territory.ETerritory;
import se.perp.c4.model.TerritoryCollection;
import se.perp.c4.net.Message;
import se.perp.c4.ui.MainWindow;
import se.perp.c4.ui.PieceCollection;
import se.perp.c4.ui.PieceOrderer;
import se.perp.c4.ui.TerritorySelectionPanel;

enum RetreatMode {

    END_TURN_WHEN_DONE,
    CHECK_CONTINUED_BATTLE_WHEN_DONE,
    FRODO_INSTA_RETREAT,
    DO_NOTHING_WHEN_DONE,
    JUST_NOTIFY_WHEN_DONE
}


class RetreatHandler implements ITerritorySelectionListener {

    private final Actor attacker;
    private final Actor retreater;
    private final ETerritory retreatingFrom;
    private final TerritoryCollection terrColl;
    private final PieceCollection pieceColl;
    private final MainWindow mainWindow;
    private Container savedPanel;
    private final IMessenger conn;
    private final IGameController controller;
    private final RetreatMode mode;

    public RetreatHandler(
            final MainWindow mw,
            final Actor attackingActor,
            final Actor retreater,
            final ETerritory retreatingFrom,
            final TerritoryCollection tc,
            final PieceCollection pc,
            final IMessenger conn,
            final IGameController controller,
            final RetreatMode retreatMode) {
        mainWindow = mw;
        attacker = attackingActor;
        this.retreater = retreater;
        this.retreatingFrom = retreatingFrom;
        terrColl = tc;
        pieceColl = pc;
        this.conn = conn;
        this.controller = controller;
        mode = retreatMode;

        List<ETerritory> possibleRetreats;
        if (retreater.isDark() || retreatMode == RetreatMode.FRODO_INSTA_RETREAT) {
            possibleRetreats = terrColl.getValidSidewaysRetreats(retreater, retreatingFrom);
        } else {
            possibleRetreats = terrColl.getValidBackwardsRetreats(retreater, retreatingFrom);
        }

        savedPanel = mainWindow.getContainer();

        TerritorySelectionPanel tsp = new TerritorySelectionPanel(
                savedPanel,
                this,
                possibleRetreats);

        mainWindow.setContainer(tsp);

        mainWindow.repaint();
    }

    public void territorySelected(ETerritory et) {
        Logger logger = Logger.getLogger(RetreatHandler.class.getName());
        logger.info("Retreat territory selected " + et);

        Territory from = terrColl.get(retreatingFrom);
        Territory to = terrColl.get(et);

        Move move = new Move(retreater.who, Actor.EActor.NOBODY, retreatingFrom, et);

        conn.sendMessage(Message.newRetreatMove(move));

        terrColl.moveActor(retreater, et);
        PieceOrderer.orderIn(terrColl, pieceColl, from);
        PieceOrderer.orderIn(terrColl, pieceColl, to);

        mainWindow.setContainer(savedPanel);
        mainWindow.repaint();

        switch (mode) {
            case END_TURN_WHEN_DONE:
                controller.nextPlayer();
                break;
            case DO_NOTHING_WHEN_DONE:
                break;
            case CHECK_CONTINUED_BATTLE_WHEN_DONE:
            // Fall through
            case FRODO_INSTA_RETREAT:
                controller.battleCheckContinued(attacker, from);
                break;
            case JUST_NOTIFY_WHEN_DONE:
                controller.retreatPerformed(move);
                break;
            default:
                break;
        }
    }
}

